package com.zby.service.imp;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zby.common.utils.ResultEnum;
import com.zby.common.exception.BlogException;
import com.zby.mapper.ArticleMapper;
import com.zby.mapper.CommentMapper;
import com.zby.model.pojo.Article;
import com.zby.model.pojo.Comment;
import com.zby.service.ArticleService;
import com.zby.common.utils.ResultUtil;
import com.zby.common.utils.JwtUtils;
import com.zby.vo.ArticleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class ArticleServiceImp extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ArticleMapper articleMapper;
    
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private CommentMapper commentMapper;

    @Override
    public int addArticle(Article article) {
        return articleMapper.addArticle(article);
    }

    @Override
    public List<ArticleVo> selectArticle() {
        return articleMapper.selectArticle();
    }

    @Override
    public int updateArticle(Article article) {
        int affectedRows = articleMapper.updateArticle(article);
        if (affectedRows > 0) {
            return 1;
        }
        return 0;
    }

    @Override
    public ArticleVo selectArticleContent(Integer id) {
        //  todo 1.从缓存中查询文章内容
        String article = redisTemplate.opsForValue().get("article:" + id);
        System.out.println("article:" +article);
        if(StrUtil.isNotBlank(article)){
            // 缓存不为空，从缓存中解析
            ArticleVo articleVo = JSONUtil.toBean(article, ArticleVo.class);
            System.out.println("article:" +articleVo);
            return articleVo;
        } else {
            // 缓存为空，从数据库查询
            ArticleVo articleVo = articleMapper.selectArticleContent(id);
            // 设置null值防止缓存穿透
            if( articleVo == null){
                // 数据库中也不存在，缓存空值，设置较短过期时间
                // 5分钟
                redisTemplate.opsForValue().set("article:" + id, "null", 30, TimeUnit.MINUTES);
            }
            // 缓存文章内容
            redisTemplate.opsForValue().set("article:" + id, JSONUtil.toJsonStr(articleVo), 30, TimeUnit.MINUTES);

            return articleVo;
        }
    }

    @Transactional(rollbackFor = BlogException.class)
    @Override
    public int del(List<Integer> ids) {
        // 删除文章
        int count = articleMapper.deleteByIds(ids);
        // 删除文章数量不一致抛出异常
        if (count != ids.size()) {
            throw new BlogException(ResultEnum.FAIL.getCode(), MessageFormat.format("有{0}个文章删除失败", ids.size() - count));
        }
        // 构建查询条件
        LambdaQueryWrapper<Comment> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Comment::getArticleId, ids);
        // 删除评论
        commentMapper.delete(wrapper);
        return count;
    }

    @Override
    public int updateViewLikes(Integer articleId, int i) {
        int update = articleMapper.updateViewLikes(articleId, i);
        return update;
    }

    @Override
    public int updateAddViewLikes(Integer articleId, Integer number) {
        int update = articleMapper.updateAddViewLikes(articleId, number);
        return update;
    }
    
    @Override
    public ResultUtil<List<ArticleVo>> getPersonalArticle(String token) {
        // 解析token获取用户ID
        Integer userId = Integer.valueOf(jwtUtils.parseToken(token).get("id").toString());
        // 根据用户ID查询个人文章
        List<ArticleVo> articleVos = articleMapper.selectPersonalArticle(userId);
        return ResultUtil.success(articleVos);
    }
}